package com.yundasys.lab12java.lambda.stream;

import org.junit.Before;
import org.junit.Test;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author jiangta
 * @version 1.0
 * @date 2021/6/3 9:10 上午
 */
public class StreamTest {

    private List<String> stringCollection = null;

    @Before
    public void before() {
        stringCollection = new ArrayList<>();
        stringCollection.add("ddd2");
        stringCollection.add("aaa2");
        stringCollection.add("bbb1");
        stringCollection.add("aaa1");
        stringCollection.add("bbb3");
        stringCollection.add("ccc");
        stringCollection.add("bbb2");
        stringCollection.add("ddd1");
    }

    @Test
    public void test(){
        B b = new B();
        b.scan();  //我的输出结果是什么？
    }
    static class A {
        public void scan(){
            doScan();
        }
        protected void doScan(){
            System.out.println("A.doScan");
        }
    }
    static class B extends A {
        @Override
        protected void doScan() {
            System.out.println("B.doScan");
        }
    }

    @Test
    public void Test01() {

        IFormula formula = new IFormula() {
            @Override
            public double calculate(int a) {
                return a*a;
            }
        };
        System.out.println(formula.calculate(2));
        System.out.println(formula.sqrt(2));

        IFormula formula1 = a -> a*a;
        System.out.println(formula1.calculate(2));
        System.out.println(formula1.sqrt(2));
    }

    @Test
    public void test17(){
        stringCollection.stream().filter(s-> s.startsWith("a"))
                .forEach(System.out::println);
    }

    @Test
    public void test18() {
        stringCollection.stream().sorted()
                .filter(s-> s.startsWith("a"))
                .forEach(System.out::println);
        System.out.println(stringCollection);
    }

    @Test
    public void test19() {
        stringCollection.stream()
                .map(String::toUpperCase)
                .sorted(Comparator.reverseOrder())
                .forEach(System.out::println);
    }

    @Test
    public void test20(){
        //// anyMatch：验证 list 中 string 是否有以 a 开头的, 匹配到第一个，即返回 true
        boolean anyStartsWithA = stringCollection.stream().anyMatch(s -> s.startsWith("a"));
        System.out.println(anyStartsWithA);//true

        // allMatch：验证 list 中 string 是否都是以 a 开头的
        boolean allStartsWithA = stringCollection.stream().allMatch(s -> s.startsWith("a"));
        System.out.println(allStartsWithA);//false

        // noneMatch：验证 list 中 string 是否都不是以 z 开头的
        boolean z = stringCollection.stream().noneMatch(s -> s.startsWith("z"));
    }

    @Test
    public void test21() {
        // count：先对 list 中字符串开头为 b 进行过滤，让后统计数量
        long b = stringCollection.stream().filter(s -> s.startsWith("b")).count();
        System.out.println(b);
    }

    @Test
    public void test22() {
        Optional<String> reduce = stringCollection.stream().sorted().reduce((s1, s2) -> s1 + "#" + s2);
        reduce.ifPresent(System.out::println);
    }

    @Test
    public void test23() {
        int max = 1000000;
        List<String> values = new ArrayList<>(max);
        for (int i = 0; i < max; i++) {
            UUID uuid = UUID.randomUUID();
            values.add(uuid.toString());
        }
        // 纳秒
        long t0 = System.nanoTime();
        long count = values.stream().sorted().count();
        System.out.println(count);
        long t1 = System.nanoTime();
        // 纳秒转微秒
        long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
        System.out.println(String.format("顺序流排序耗时: %d ms", millis));
        //顺序流排序耗时: 712 ms
    }

    @Test
    public void test24(){
        int max = 1000000;
        List<String> values = new ArrayList<>(max);
        for (int i = 0; i < max; i++) {
            UUID uuid = UUID.randomUUID();
            values.add(uuid.toString());
        }
        long t0 = System.nanoTime();
        long count = values.parallelStream().sorted().count();
        System.out.println(count);
        long t1 = System.nanoTime();
        long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
        System.out.println(String.format("parallel sort took: %d ms", millis));
        //parallel sort took: 385 ms
    }

    @Test
    public void test25() {
        Map<Integer, String> map = new HashMap<>();
        for (int i = 0; i < 10; i++) {
            // 与老版不同的是，putIfAbent() 方法在 put 之前，  不用在写if null continue了
            // 会判断 key 是否已经存在，存在则直接返回 value, 否则 put, 再返回 value
            map.putIfAbsent(i, "val" + i);
        }
        map.forEach((key,value)-> System.out.println("key:"+key+ " "+"value:"+value));
    }

    @Test
    public void test31() {
        Clock clock = Clock.systemDefaultZone();
        long millis = clock.millis();
        Instant instant = clock.instant();
        Date from = Date.from(instant);
        System.out.println(from);
    }

    @Test
    public void test32() {
        System.out.println(ZoneId.getAvailableZoneIds());
        // prints all available timezone ids

        ZoneId zone1 = ZoneId.of("Europe/Berlin");
        ZoneId zone2 = ZoneId.of("Brazil/East");
        System.out.println(zone1.getRules());
        System.out.println(zone2.getRules());

        //[Asia/Aden, America/Cuiaba, Etc/GMT+9, Etc/Gada/Atlantic, Atlantic/St_Helena, Australia/Tasmania, Libya, Europe/Guernsey, America/Grand_Turk, US/Pacific-New, Asia/Samarkand, America/Argentina/Cordoba, Asia/Phnom_Penh, Africa/Kigali, Asia/Almaty, US/Alaska, Asi...
        // ZoneRules[currentStandardOffset=+01:00]
        // ZoneRules[currentStandardOffset=-03:00]
    }

    @Test
    public void test33(){
        ZoneId zone1 = ZoneId.of("Europe/Berlin");
        ZoneId zone2 = ZoneId.of("Brazil/East");
        LocalTime now1 = LocalTime.now(zone1);
        LocalTime now2 = LocalTime.now(zone2);
        System.out.println(now1.isBefore(now2));  // false
        long hoursBetween = ChronoUnit.HOURS.between(now1, now2);
        long minutesBetween = ChronoUnit.MINUTES.between(now1, now2);
        System.out.println(hoursBetween);       // -3
        System.out.println(minutesBetween);     // -239
    }

    @Test
    public void test34() {
        LocalTime late = LocalTime.of(23,59,59);
        System.out.println(late);

        DateTimeFormatter germanFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
                .withLocale(Locale.GERMAN);
        LocalTime lettTime = LocalTime.parse("13:37", germanFormatter);
        System.out.println(lettTime);
    }

    @Test
    public void test35() {
        LocalDate today = LocalDate.now();
        //// 今天加一天
        LocalDate tomorrow = today.plus(1, ChronoUnit.DAYS);
        // 明天减两天
        LocalDate yesterday = tomorrow.minusDays(2);

    }

    @Test
    public void test37() {
        LocalDateTime localDateTime = LocalDateTime.of(2014, Month.DECEMBER, 31, 23, 59, 59);
        DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();
        System.out.println(dayOfWeek);
        Month month = localDateTime.getMonth();
        System.out.println(month);
        // 获取改时间是该天中的第几分钟
        long aLong = localDateTime.getLong(ChronoField.MINUTE_OF_DAY);
        System.out.println(aLong);
    }

    @Test
    public void test38() {
        LocalDateTime localDateTime = LocalDateTime.of(2014, Month.DECEMBER, 31, 23, 59, 59);
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        Date from = Date.from(instant);
        System.out.println(from);
    }

    @Test
    public void test39() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM dd, yyyy - HH:mm");
        LocalDateTime localDateTime = LocalDateTime.parse("11 03, 2014 - 07:13", formatter);
        String format = formatter.format(localDateTime);
        String format1 = localDateTime.format(formatter);
        System.out.println(format);
        System.out.println(format1);
    }

}
